package tests.ge;

import ge.HandCodedSolution;
import problems.nbitparity.ParityFitnessEvaluator;
import problems.nbitparity.ParityProblem.ExpressionEvaluator;

public class RandomTests {
	public static void main(String[] args) {
		int num_bits = 3;
		String[] parameter_names = { "a", "b", "c" };
		Class<?>[] parameter_types = { Boolean.class, Boolean.class,
				Boolean.class, };
		Class<Boolean> return_type = Boolean.class;

		ExpressionEvaluator ee = new ExpressionEvaluator(
				"(a && !b && (!c)) || (!a && (!b) && c) || ((!a) && b && !c) || (a && b && c)", return_type,
				parameter_names, parameter_types);

		Boolean[] inputs = new Boolean[num_bits];
		double fitness = 0;
		int tmp, pos;
		for (int i = 0; i < Math.pow(2, inputs.length); i++) {
			tmp = i;

			for (int j = inputs.length - 1; j >= 0; j--) {
				pos = (int) Math.pow(2, j);
				inputs[j] = ((int) (tmp / pos) == 0 ? false : true);
				tmp -= (inputs[j] ? 1 : 0) * pos;
			}

			boolean solution_parity = ee.execute(inputs);

			int count = 0;
			for (int idx = 0; idx < inputs.length; idx++) {
				if (inputs[idx]) {
					count++;
				}
			}
			boolean real_parity = (count % 2 == 1);

			if (solution_parity != real_parity) {
				fitness -= 1;
				for ( boolean var : inputs) {
					System.out.print(var);
					System.out.print(' ');
				}
				System.out.print(':');
				System.out.print(solution_parity);
				System.out.print(" <> ");
				System.out.println(real_parity);
			}

		}
		System.out.println(fitness);
		
		ParityFitnessEvaluator eval = new ParityFitnessEvaluator();
		int[] ints = {
				//(a & b & c) | (a & !b & !c) | (!a & b & !c) | (!a & !b & c) 

				// (a & b & c)
				// e
				0, // e op e
				1, // (e) => (e) op e
				0, // e op e => (e op e) op e
				3, // bit => (bit op e) op e
				0, // a => (a op e) op e
				0, // & => (a & e) op e
				0, // e op e => (a & e op e) op e
				3, // bit
				1, // b => (a & b op e) op e
				0, // & => (a & b & e) op e
				3, // bit
				2, // c => (a & b & c) op e
				1, // | => (a & b & c) | e

				// (a & !b & !c)
				0, // e op e => (a & b & c) | e op e
				1, // (e) => (a & b & c) | (e) op e
				0, // e op e => (a & b & c) | (e op e) op e
				3, // bit => (a & b & c) | (bit op e) op e
				0, // a => (a & b & c) | (a op e) op e
				0, // & => (a & b & c) | (a & e) op e
				0, // e op e => (a & b & c) | (a & e op e) op e
				2, // uop(e) => (a & b & c) | (a & uop(e) op e) op e
				0, // ! => (a & b & c) | (a & !(e) op e) op e
				3, // bit
				1, // b => (a & b & c) | (a & !(b) op e) op e
				0, // & => (a & b & c) | (a & !(b) & e) op e
				2, // uop(e) => (a & b & c) | (a & !(b) & uop(e)) op e
				0, // ! => (a & b & c) | (a & !(b) & !(e)) op e
				3, // bit
				2, // c => (a & b & c) | (a & !(b) & !(c)) op e
				1, // | => (a & b & c) | (a & !(b) & !(c)) | e

				// (!a & b & !c)
				0, // e op e => (a & b & c) | (a & !(b) & !(c)) | e op e
				1, // (e) => (a & b & c) | (a & !(b) & !(c)) | (e) op e
				0, // e op e => (a & b & c) | (a & !(b) & !(c)) | (e op e) op e
				2, // uop(e)
				0, // ! => (a & b & c) | (a & !(b) & !(c)) | (!(e) op e) op e
				3, // bit => (a & b & c) | (a & !(b) & !(c)) | (!(bit) op e) op e
				0, // a => (a & b & c) | (a & !(b) & !(c)) | (!(a) op e) op e
				0, // & => (a & b & c) | (a & !(b) & !(c)) | (!(a) & e) op e
				0, // e op e => (a & b & c) | (a & !(b) & !(c)) | (!(a) op e op e) op e
				3, // bit 
				1, // b => (a & b & c) | (a & !(b) & !(c)) | (!(a) & b op e) op e
				0, // & => (a & b & c) | (a & !(b) & !(c)) | (!(a) & b & e) op e
				2, // uop(e) 
				0, // ! => (a & b & c) | (a & !(b) & !(c)) | (!(a) & b & !(e)) op e
				3, // bit
				2, // c => (a & b & c) | (a & !(b) & !(c)) | (!(a) & b & !(c)) op e
				1, // | => (a & b & c) | (a & !(b) & !(c)) | (!(a) & b & !(c)) | e

				// (!a & !b & c)
				1, // (e) => (a & b & c) | (a & !(b) & !(c)) | (!(a) & b & !(c)) | (e)
				0, // e op e => (a & b & c) | (a & !(b) & !(c)) | (!(a) & b & !(c)) | (e op e)
				2, // uop(e)
				0, // ! => (a & b & c) | (a & !(b) & !(c)) | (!(a) & b & !(c)) | (!(e) op e)
				3, // bit => (a & b & c) | (a & !(b) & !(c)) | (!(a) & b & !(c)) |  (!(bit) op e)
				0, // a => (a & b & c) | (a & !(b) & !(c)) | (!(a) & b & !(c)) | (!(a) op e)
				0, // & => (a & b & c) | (a & !(b) & !(c)) | (!(a) & b & !(c)) | (!(a) & e)
				0, // e op e => (a & b & c) | (a & !(b) & !(c)) | (!(a) & b & !(c)) | (!(a) & e op e)
				2, // uop(e)
				0, // ! => (a & b & c) | (a & !(b) & !(c)) | (!(a) & b & !(c)) | (!(a) & !(e) op e)
				3, // bit
				1, // b => (a & b & c) | (a & !(b) & !(c)) | (!(a) & b & !(c)) | (!(a) & !(b) op e)
				0, // & => (a & b & c) | (a & !(b) & !(c)) | (!(a) & b & !(c)) | (!(a) & !(b) & e)
				3, // bit
				2, // c => (a & b & c) | (a & !(b) & !(c)) | (!(a) & b & !(c)) | (!(a) & !(b) & c)
		};
		
		HandCodedSolution solution = new HandCodedSolution(ints );
		
		System.out.println(eval.getFitness(solution));
	}
}
